package co.fitstart.mobile.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;

import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.courseware.dietary.Dietary;
import co.fitstart.entity.courseware.dietary.DietaryProgram;
import co.fitstart.entity.courseware.dietary.DietaryProgramType;
import co.fitstart.entity.courseware.exercise.Exercise;
import co.fitstart.entity.courseware.exercise.PlannedSchedule;
import co.fitstart.entity.courseware.fitnessgroup.BatchCourseware;
import co.fitstart.mobile.service.WeeklyPlanService;

/**
 * 
 * @author haiyan_xiao
 *
 */
@Service("weeklyPlanService")
public class WeeklyPlanServiceImpl implements WeeklyPlanService {
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.coach.service.WeeklyPlanService#loadDietary(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    public Dietary loadDietary(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForObject("FROM Dietary WHERE disabled = false"
                + " AND batch = :batch", "batch", batchCourseware, Dietary.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.coach.service.WeeklyPlanService#generallyLoadDietary(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    @SuppressWarnings("unlikely-arg-type")
	public Dietary generallyLoadDietary(BatchCourseware batchCourseware) {
        Dietary dietary = this.loadDietary(batchCourseware);
        
        if(dietary == null) {
            Map<String, DietaryProgram> dietaryPrograms = batchCourseware.getDietaryPrograms();
            if(dietaryPrograms != null) {
                Dietary newDietary = new Dietary(batchCourseware);
                
                if(dietaryPrograms.get(DietaryProgramType.BREAKFAST) != null) {
                    newDietary.setBreakfastTemplate(dietaryPrograms.get(DietaryProgramType.BREAKFAST).getTemplate());
                    newDietary.setBreakfastDescription(dietaryPrograms.get(DietaryProgramType.BREAKFAST).getDescription());
                    if(dietaryPrograms.get(DietaryProgramType.BREAKFAST).getSnacks() != null) {
                        DietaryProgram breakfastSnack = genericDaoSupport.load(DietaryProgram.class, dietaryPrograms.get(DietaryProgramType.BREAKFAST).getSnacks());
                        
                        if(breakfastSnack != null) {
                            newDietary.setBreakfastSnackTemplate(breakfastSnack.getTemplate());
                            newDietary.setBreakfastSnackDescription(breakfastSnack.getDescription());
                        }
                    }
                }
                
                if(dietaryPrograms.get(DietaryProgramType.LUNCH) != null) {
                    newDietary.setLunchTemplate(dietaryPrograms.get(DietaryProgramType.LUNCH).getTemplate());
                    newDietary.setLunchDescription(dietaryPrograms.get(DietaryProgramType.LUNCH).getDescription());
                    if(dietaryPrograms.get(DietaryProgramType.LUNCH).getSnacks() != null) {
                        DietaryProgram lunchSnack = genericDaoSupport.load(DietaryProgram.class, dietaryPrograms.get(DietaryProgramType.LUNCH).getSnacks());
                        
                        if(lunchSnack != null) {
                            newDietary.setLunchSnackTemplate(lunchSnack.getTemplate());
                            newDietary.setLunchSnackDescription(lunchSnack.getDescription());
                        }
                    }
                }
                
                if(dietaryPrograms.get(DietaryProgramType.DINNER) != null) {
                    newDietary.setDinnerTemplate(dietaryPrograms.get(DietaryProgramType.DINNER).getTemplate());
                    newDietary.setDinnerDescription(dietaryPrograms.get(DietaryProgramType.DINNER).getDescription());
                    if(dietaryPrograms.get(DietaryProgramType.DINNER).getSnacks() != null) {
                        DietaryProgram dinnerSnack = genericDaoSupport.load(DietaryProgram.class, dietaryPrograms.get(DietaryProgramType.DINNER).getSnacks());
                        
                        if(dinnerSnack != null) {
                            newDietary.setDinnerSnackTemplate(dinnerSnack.getTemplate());
                            newDietary.setDinnerSnackDescription(dinnerSnack.getDescription());
                        }
                    }
                }
                
                genericDaoSupport.save(newDietary);
                return newDietary;
            } else {
                return null;
            }
        } else {
            return dietary;
        }
    }
    
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.coach.service.WeeklyPlanService#loadExercise(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    public Exercise loadExercise(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForObject("FROM Exercise WHERE disabled = false"
                + " AND batch = :batch", "batch", batchCourseware, Exercise.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.coach.service.WeeklyPlanService#listPlannedSchedule(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    @SuppressWarnings("unchecked")
    public List<PlannedSchedule> listPlannedSchedule(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForList("FROM PlannedSchedule WHERE disabled = false"
                + " AND batch = :batch ORDER BY day ASC", "batch", batchCourseware);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.coach.service.WeeklyPlanService#listSchedule(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, java.util.List)
     */
    @SuppressWarnings("unchecked")
    public Map<Integer, CourseSchedule> listSchedule(BatchCourseware batchCourseware, List<PlannedSchedule> schedules) {
        if(schedules.isEmpty()) {
            return null;
        } else {
            int begin = 0;
            if(batchCourseware.getSorting() > 1) {
                Map<String, Object> parameters = new HashMap<>();
                parameters.put("courseRound", batchCourseware.getCourseRound());
                parameters.put("sorting", batchCourseware.getSorting());
                
                begin = genericDaoSupport.count("FROM PlannedSchedule WHERE disabled = false"
                        + " AND batch.courseRound = :courseRound AND batch.sorting < :sorting"
                        + " AND content IS NOT NULL", parameters);
            }
            
            Map<String, Object> scheduleParameters = new HashMap<>();
            scheduleParameters.put("courseRound", batchCourseware.getCourseRound());
            scheduleParameters.put("scheduleStatus", new ScheduleStatus[]{ScheduleStatus.READY, ScheduleStatus.EXPIRY, ScheduleStatus.FINISH});
            
            List<CourseSchedule> courseSchedules = genericDaoSupport.searchForList("FROM CourseSchedule WHERE disabled = false"
                    + " AND courseRound = :courseRound AND scheduleStatus in (:scheduleStatus) ORDER BY occurDate ASC,occurHour ASC",
                    scheduleParameters, begin, schedules.size());
            
            if(courseSchedules.isEmpty()) {
                return null;
            } else {
                Map<Integer, CourseSchedule> map = new HashMap<>();
                
                for(int i=0; i <courseSchedules.size(); i++) {
                    map.put(schedules.get(i).getDay(), courseSchedules.get(i));
                }
                
                return map;
            }
        }
    }
    

    /*
     * (non-Javadoc)
     * @see co.fitstart.mobile.service.WeeklyPlanService#getPlannedSchedule(co.fitstart.entity.course.schedule.CourseSchedule, int)
     */
    @SuppressWarnings("unchecked")
    public PlannedSchedule getPlannedSchedule(CourseSchedule courseSchedule, int rank) {
        List<PlannedSchedule> plannedSchedules = genericDaoSupport.searchForList(
                "FROM PlannedSchedule WHERE disabled=false"
                + " AND content IS NOT NULL AND batch.courseRound=:courseRound"
                + " ORDER BY batch.sorting ASC,day ASC", "courseRound",
                courseSchedule.getCourseRound(), rank - 1, 1);
        return plannedSchedules.isEmpty() ? null : plannedSchedules.get(0);
    }
}
